#include "DXUT.h"
#include "RenderAssistLine.h"


CRenderAssistLine::CRenderAssistLine(void):RenderTech()
{
	m_pAssistLineVB = NULL;
	m_pAssistLineVBLayout = NULL;
	m_iNumAssistVertices = 0;

	m_pRenderTech = NULL;
	m_pWorldViewProjMat = NULL;

	m_bPtsReady = false;
}


CRenderAssistLine::~CRenderAssistLine(void)
{
	m_ptArray.RemoveAll();
	OnD3D11DestroyDevice(NULL);
}

void CRenderAssistLine::InitEffectsVariables()
{
	if(!m_pEffect) 
	{
#ifdef _DEBUG
		OUTPUTERRORINFO;
#endif
		return;
	}	
	m_pRenderTech = m_pEffect->GetTechniqueByName("RenderAssistLine");
	m_pWorldViewProjMat = m_pEffect->GetVariableByName("mWorldViewProjection")->AsMatrix();
}

void CRenderAssistLine::ReloadEffectsDebug(ID3D11Device* pd3dDevice, CDirectoryUtil* pDirUtil)
{
	SAFE_RELEASE(m_pEffect);
	//create effects
	TCHAR ShaderFileDir[MAX_PATH];
	enum SUBDIRECTORY subfolder = SUBDIRECTORY::SHADERSDIR;
	pDirUtil->GetAbsoluteFileFolder(L"RenderAssistLine.fx",subfolder, ShaderFileDir);
	HRESULT hr = CD3DUtilityFunction::CreateEffectsFromFile(pd3dDevice, ShaderFileDir, NULL, "fx_5_0", &m_pEffect);
	InitEffectsVariables();
}

HRESULT CRenderAssistLine::OnD3D11CreateDevice(ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, CDirectoryUtil* pDirUtil, void* pUserContext)
{
	HRESULT hr = S_OK;
	m_iNumAssistVertices = m_ptArray.GetSize();
	if(m_iNumAssistVertices == 0 || !m_bPtsReady)
	{
		printf("please initialize the points array firstly!\n");
		return E_FAIL;
	}
	//buffer
	D3D11_BUFFER_DESC BufferDesc;
	BufferDesc.ByteWidth = m_iNumAssistVertices * sizeof(PT_VertColor);
	BufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
	BufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	BufferDesc.CPUAccessFlags = 0;
	BufferDesc.MiscFlags = 0;

	D3D11_SUBRESOURCE_DATA InitData;
	InitData.pSysMem = m_ptArray.GetData();
	SAFE_RELEASE(m_pAssistLineVB);
	V_RETURN( pd3dDevice->CreateBuffer( &BufferDesc, &InitData, &m_pAssistLineVB ) );

	//create effects
	TCHAR ShaderFileDir[MAX_PATH];
	enum SUBDIRECTORY subfolder = SUBDIRECTORY::SHADERSDIR;
	pDirUtil->GetAbsoluteFileFolder(L"RenderAssistLine.fx",subfolder, ShaderFileDir);
	hr = CD3DUtilityFunction::CreateEffectsFromFile(pd3dDevice, ShaderFileDir, NULL, "fx_5_0", &m_pEffect);
	InitEffectsVariables();
	//create vertex layout
	const D3D11_INPUT_ELEMENT_DESC layout[2] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	//vb layout
	SAFE_RELEASE(m_pAssistLineVBLayout);
	V(CD3DUtilityFunction::CreateVertexLayout(pd3dDevice,layout,ARRAYSIZE(layout), m_pRenderTech, &m_pAssistLineVBLayout));

	return hr;
}

HRESULT CRenderAssistLine::OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, 
	CDirectoryUtil* pDirUtil, void* pUserContext )
{
	return S_OK;
}

void CRenderAssistLine::OnD3D11ReleasingSwapChain( void* pUserContext )
{
	return;
}

void CRenderAssistLine::OnD3D11DestroyDevice( void* pUserContext )
{
	SAFE_RELEASE(m_pAssistLineVB);
	SAFE_RELEASE(m_pAssistLineVBLayout);
	RenderTech::OnD3D11DestroyDevice(pUserContext);
}

void CRenderAssistLine::OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, CBaseCamera* pViewCamera, 
	CDirectoryUtil* pDirUtil, double fTime, float fElapsedTime, void* pUserContext )
{
	if (!m_bPtsReady)
	{
		printf("ERROR: please initialize the pts array firstly!\n");
			return;
	}

	CModelViewerCamera* pCamera = static_cast<CModelViewerCamera*>(pViewCamera);
	D3DXMATRIX mWorld = *(pCamera->GetWorldMatrix());
	D3DXMATRIX mView = *(pCamera->GetViewMatrix());
	D3DXMATRIX mProj = *(pCamera->GetProjMatrix());
	D3DXMATRIX mWorldViewProjection = mWorld * mView * mProj;


	// Set render resources
	pd3dImmediateContext->IASetInputLayout( m_pAssistLineVBLayout );
	ID3D11Buffer* pVB[1] = { m_pAssistLineVB };
	UINT pStride[1] = { sizeof(PT_VertColor) };
	UINT pOffset[1] = { 0 };
	pd3dImmediateContext->IASetVertexBuffers( 0, 1, pVB, pStride, pOffset );
	pd3dImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_LINELIST);

	// Render objects here...
	// Apply the technique contained in the effect 
	D3DX11_TECHNIQUE_DESC Desc;
	m_pRenderTech->GetDesc( &Desc );
	m_pWorldViewProjMat->SetMatrix((float*)(&mWorldViewProjection));

	for( UINT iPass = 0; iPass < Desc.Passes; iPass++ )
	{
		m_pRenderTech->GetPassByIndex( iPass )->Apply( 0, pd3dImmediateContext );
		pd3dImmediateContext->Draw(m_iNumAssistVertices,0);		
	}

}